<!DOCTYPE html>
<html>

<head>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">


    <title>H+ 后台主题UI框架 - 百度ECHarts</title>
    <meta name="keywords" content="H+后台主题,后台bootstrap框架,会员中心主题,后台HTML,响应式后台">
    <meta name="description" content="H+是一个完全响应式，基于Bootstrap3最新版本开发的扁平化主题，她采用了主流的左右两栏式布局，使用了Html5+CSS3等现代技术">

    <link href="css/bootstrap.min.css?v=3.4.0" rel="stylesheet">
    <link href="css/font-awesome.min93e3.css" rel="stylesheet">

    <link href="css/animate.min.css" rel="stylesheet">
    <link href="css/style.min.css?v=3.2.0" rel="stylesheet">
    <style type="text/css">
        .node circle {
            cursor: pointer;
            fill: #fff;
            stroke: steelblue;
            stroke-width: 2px;
        }

        .node text {
            font-size: 14px;
        }

        .link {
            fill: none;
            stroke: #ccc;
            stroke-width: 1.5px;
        }

        .no-skin {
            position: relative;
            text-align: center;
        }

        .svg-tip {
            padding: 10px 18px;
            position: absolute;
            left: 0;
            top: 0;
            background: #fff;
            box-shadow: 1px 1px 4px #333;
            display: none;
        }
        .state-form-group{
            margin: 0;
            padding-top: 10px;
        }



        #page-wrapper{margin: 0;}
    </style>
</head>

<body class="gray-bg">
<div class="row  border-bottom white-bg dashboard-header">
    <div class="col-sm-12">
        <p>
            D3.js is a JavaScript library for manipulating documents based on data. D3 helps you bring data to life
            using HTML, SVG, and CSS. D3’s emphasis on web standards gives you the full capabilities of modern browsers
            without tying yourself to a proprietary framework, combining powerful visualization components and a
            data-driven approach to DOM manipulation.
        </p>
        <p>D3官网：<a href="https://d3js.org/" target="_blank">https://d3js.org/</a></p>
        <p>我们只使用它的组织结构树模块，其他图表还是使用Echarts</p>
    </div>

</div>
<div class="wrapper wrapper-content animated fadeInRight">
    <div class="row">
        <div class="col-sm-12">
            <div class="ibox float-e-margins">
                <div class="ibox-title">
                    <h5>组织结构树</h5>
                </div>
                <div class="ibox-content">
                    <div class="main-container" id="main-container">
                        <div class="main-content" id="page-wrapper">

                        </div>
                    </div>
                    <div class="svg-tip"></div>
                </div>
            </div>
        </div>
    </div>

</div>
<!-- 全局js -->
<script src="js/jquery.min.js"></script>
<script src="js/bootstrap.min.js?v=3.4.0"></script>
<script src="js/d3.min.js"></script>
<script type="text/javascript">

    function init() {
        var width = 960;
        var height = 500;

        $('.main-content').html("");
        //边界空白
        var padding = {left: 120, right: 120, top: 40, bottom: 40};

        var svg = d3.select(".main-content")
            .append("svg")
            .attr("width", width + padding.left + padding.right)
            .attr("height", height + padding.top + padding.bottom)
            .append("g")
            .attr("transform", "translate(" + padding.left + "," + padding.top + ")");

        //树状图布局
        var tree = d3.layout.tree()
            .size([height, width]);

        //对角线生成器
        var diagonal = d3.svg.diagonal()
            .projection(function (d) {
                return [d.y, d.x];
            });


        d3.json("js/tsconfig.json",function(error,root){


            //给第一个节点添加初始坐标x0和x1
            root.x0 = height / 2;
            root.y0 = 0;

            //以第一个节点为起始节点，重绘
            redraw(root);

            //重绘函数
            function redraw(source) {

                /*
                 （1） 计算节点和连线的位置
                 */

                //应用布局，计算节点和连线
                var nodes = tree.nodes(root);
                var links = tree.links(nodes);

                //重新计算节点的y坐标
                nodes.forEach(function (d) {
                    d.y = d.depth * 180;
                });

                /*
                 （2） 节点的处理
                 */

                //获取节点的update部分
                var nodeUpdate = svg.selectAll(".node")
                    .data(nodes, function (d) {
                        return d.path;
                    });

                //获取节点的enter部分
                var nodeEnter = nodeUpdate.enter();

                //获取节点的exit部分
                var nodeExit = nodeUpdate.exit();

                //1. 节点的 Enter 部分的处理办法
                var enterNodes = nodeEnter.append("g")
                    .attr("class", "node")
                    .attr("transform", function (d) {
                        return "translate(" + source.y0 + "," + source.x0 + ")";
                    })
                    .on("mouseover", function (d) {
                        if (d.data) {
                            $('.svg-tip').text(d.data).css({"top": d.x0 - 20 + 'px'}).css({'left': d.y0 + 90 + 'px'}).css({"display": "block"})
                        }
                    })
                    .on("mouseout", function (d) {

                        $('.svg-tip').text(d.data).css({"display": "none"})
                    })
                    .on("click", function (d) {
                        toggle(d);
                        redraw(d);
                    });

                enterNodes.append("circle")
                    .attr("r", 0)
                    .style("fill", function (d) {
                        return d._children ? "lightsteelblue" : "#fff";
                    });

                enterNodes.append("text")
                    .attr("x", function (d) {
                        return d.children || d._children ? -14 : 14;
                    })
                    .attr("dy", ".35em")
                    .attr("data-show", function (d) {
                        return d.data;
                    })
                    .attr("text-anchor", function (d) {
                        return d.children || d._children ? "end" : "start";
                    })
                    .text(function (d) {
                        return d.name;
                    })
                    .style("fill-opacity", 0);


                //2. 节点的 Update 部分的处理办法
                var updateNodes = nodeUpdate.transition()
                    .duration(500)
                    .attr("transform", function (d) {
                        return "translate(" + d.y + "," + d.x + ")";
                    });

                updateNodes.select("circle")
                    .attr("r", 8)
                    .style("fill", function (d) {
                        return d._children ? "lightsteelblue" : "#fff";
                    });

                updateNodes.select("text")
                    .style("fill-opacity", 1);

                //3. 节点的 Exit 部分的处理办法
                var exitNodes = nodeExit.transition()
                    .duration(500)
                    .attr("transform", function (d) {
                        return "translate(" + source.y + "," + source.x + ")";
                    })
                    .remove();

                exitNodes.select("circle")
                    .attr("r", 0);

                exitNodes.select("text")
                    .style("fill-opacity", 0);

                /*
                 （3） 连线的处理
                 */

                //获取连线的update部分
                var linkUpdate = svg.selectAll(".link")
                    .data(links, function (d) {
                        return d.target.path;
                    });

                //获取连线的enter部分
                var linkEnter = linkUpdate.enter();

                //获取连线的exit部分
                var linkExit = linkUpdate.exit();

                //1. 连线的 Enter 部分的处理办法
                linkEnter.insert("path", ".node")
                    .attr("class", "link")
                    .attr("d", function (d) {
                        var o = {x: source.x0, y: source.y0};
                        return diagonal({source: o, target: o});
                    })
                    .transition()
                    .duration(500)
                    .attr("d", diagonal);

                //2. 连线的 Update 部分的处理办法
                linkUpdate.transition()
                    .duration(500)
                    .attr("d", diagonal);

                //3. 连线的 Exit 部分的处理办法
                linkExit.transition()
                    .duration(500)
                    .attr("d", function (d) {
                        var o = {x: source.x, y: source.y};
                        return diagonal({source: o, target: o});
                    })
                    .remove();


                /*
                 （4） 将当前的节点坐标保存在变量x0、y0里，以备更新时使用
                 */
                nodes.forEach(function (d) {
                    d.x0 = d.x;
                    d.y0 = d.y;
                });

            }

            //切换开关，d 为被点击的节点
            function toggle(d) {
                if (d.children) { //如果有子节点
                    d._children = d.children; //将该子节点保存到 _children
                    d.children = null;  //将子节点设置为null
                } else {  //如果没有子节点
                    d.children = d._children; //从 _children 取回原来的子节点
                    d._children = null; //将 _children 设置为 null
                }
            }

        });

        }
        $(function () {
            init();
        })

</script>

</body>

</html>